#include "number.h"

#include "bool.h"

#include <QtCore/QRegExp>
#include <QtCore/QVariant>

using namespace core;

const TypeName Number::NAME = Type::demangledName(typeid(Number).name());

Number::Number(int value) : ValueType(),
    m_value(value)
{
    m_operations.insert(OPERATION_EQUALTO, OP(Bool::NAME));
    m_operations.insert(OPERATION_NEQUALTO, OP(Bool::NAME));

    m_operations.insert(OPERATION_ADDITION, OP(NAME));
    m_operations.insert(OPERATION_SUBSTRACTION, OP(NAME));

    // ExpVal doesn't have support for unary operators yet
    //m_operations.insert(OPERATION_INCREMENT, OP(NAME));
    //m_operations.insert(OPERATION_DECREMENT, OP(NAME));
}

Number::~Number()
{

}

void Number::setValue(const QVariant& value)
{
    if (value.canConvert(QVariant::Int))
    {
        m_value = value.toInt();
    }
}

QVariant Number::getValue() const
{
    return QVariant(m_value);
}

bool Number::operator ==(const Type& type) const
{
    const Number* other = dynamic_cast<const Number *>(&type);
    return other != 0 ? m_value == other->m_value : false;
}

bool Number::operator !=(const Type& type) const
{
    const Number* other = dynamic_cast<const Number *>(&type);
    return other != 0 ? m_value != other->m_value : true;
}

bool Number::canConvert(const TypeValue& value) const
{
    QRegExp regex(keywordMask());
    QVariant variant(value);

    return regex.exactMatch(value) && variant.canConvert(QVariant::Int);
}

ValueKeywordMask Number::keywordMask() const
{
    return "\\d+";
}

Type* Number::copy() const
{
    Number* newInstance = new Number(m_value);
    return newInstance;
}

Number Number::operator+(const Number& number) const
{
    return Number(m_value + number.m_value);
}

Number Number::operator-(const Number& number) const
{
    return Number(m_value - number.m_value);
}

Number& Number::operator++()
{
    ++m_value;

    return *this;
}

Number Number::operator++(int)
{
    Number ret(m_value);
    ++(*this);

    return ret;
}

Number& Number::operator--()
{
    --m_value;

    return *this;
}

Number Number::operator--(int)
{
    Number ret(m_value);
    --(*this);

    return ret;
}
